//////////////////////////////////////////////////////////////////////////
#pragma once


//////////////////////////////////////////////////////////////////////////
// Include lesser types.
#include "Sse3.hpp"


#if defined( _WINDOWS ) || (defined( __APPLE__ ) && (defined( __SSE4_2__ ) || defined( __SSE4_1__ )))
namespace Math
{
	namespace Simd
	{
		//////////////////////////////////////////////////////////////////////////
		// Sse base implementation.
		struct Sse4 : public Sse3
		{
			static float							Dot3( F32x4_t lhs, F32x4_t rhs )
			{
				Validate( lhs );	Validate( rhs );

				__m128	dotPart		=	_mm_dp_ps( lhs, rhs, 0x77 );
				Validate( dotPart );

				float	result;
				_mm_store_ss( &result, dotPart );
				return result;
			}

			static float							Mag3( F32x4_t lhs )
			{
				Validate( lhs );

				__m128	result		=	_mm_dp_ps( lhs, lhs, 0x77 );
				result				=	_mm_sqrt_ss( result );
				Validate( result );

				float				sresult;
				_mm_store_ss( &sresult, result );
				return sresult;
			}

			static F32x4_t							Norm3( F32x4_t lhs )
			{
				Validate( lhs );

				__m128	result		=	_mm_dp_ps( lhs, lhs, 0x77 );
				result				=	_mm_sqrt_ps( result );
				result				=	_mm_div_ps( lhs, result );
				Validate( result );

				return result;
			}
		};
	}
}
#endif
